home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cc / g++-dist / collect2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-15  |  4.7 KB  |  207 lines

  1. /* Build tables of static constructors and destructors and run ld. */
  2.  
  3. #include <stdio.h>
  4.  
  5. #ifdef convex
  6.  
  7. #define TEXT_SECTION_ASM_OP ".text"
  8. #define DATA_SECTION_ASM_OP ".data"
  9.  
  10. #define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
  11.   fprintf (FILE, ".globl _%s\n", LABEL)
  12.  
  13. #define ASM_OUTPUT_LABEL(FILE, LABEL) \
  14.   fprintf (FILE, "_%s:", LABEL)
  15.  
  16. #define ASM_OUTPUT_LABELREF(FILE, LABEL) \
  17.   fprintf (FILE, "\tds.w _%s\n", LABEL)
  18.  
  19. #define ASM_OUTPUT_INT(FILE, INT) \
  20.   fprintf (FILE, "\tds.w %d\n", INT)
  21.  
  22. #endif
  23.  
  24. #if defined (__GNUC__) || defined (sparc)
  25. #define alloca __builtin_alloca
  26. #endif
  27.  
  28. extern char *mktemp (char *template);
  29.  
  30. /* Linked lists of constructor and destructor names. */
  31.  
  32. struct id 
  33. {
  34.   char *name;
  35.   struct id *next;
  36. };
  37.  
  38. /* Main program. */
  39.  
  40. main (int argc, char *argv[])
  41. {
  42.   static char codexxx[] = "/tmp/codeXXXXXX";
  43.   static char asxxx[] = "/tmp/asXXXXXX";
  44.   char *codefile, *hookfile, hooksfile[40], hookofile[40];
  45.   char *outfile = "a.out";
  46.   char *arg, ldargs[1024], cmd[1024];
  47.   FILE *inf, *outf;
  48.  
  49.   /* Make temp file names. */
  50.  
  51.   codefile = mktemp (codexxx);
  52.   hookfile = mktemp (asxxx);
  53.   sprintf (hooksfile, "%s.s", hookfile);
  54.   sprintf (hookofile, "%s.o", hookfile);
  55.  
  56.   /* Parse arguments.  Remove output file spec, pass the rest to ld. */
  57.  
  58.   ldargs[0] = '\0';
  59.   while (arg = *++argv)
  60.     {
  61.       if (! strcmp (arg, "-o"))
  62.     outfile = *++argv;
  63.       else
  64.     {
  65.       strcat (ldargs, " ");
  66.       strcat (ldargs, arg);
  67.     }
  68.     }
  69.  
  70.   /* Load the program, searching all libraries.
  71.      Use -r to save the output as a relocatable file.
  72.      Examine the namelist with nm and search it for static constructors
  73.      and destructors to call.
  74.      Write the constructor and destructor tables to a .s file. */
  75.  
  76.   sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);
  77.  
  78.   if (! (inf = popen (cmd, "r")))
  79.     fatal_perror ("Can't open pipe to ld");
  80.   if (! (outf = fopen (hooksfile, "w")))
  81.     fatal_perror ("Can't write %s", hooksfile);
  82.  
  83.   write_hooks (inf, outf);
  84.  
  85.   if (pclose (inf) || fclose (outf))
  86.     fatal ("load failed");
  87.  
  88.   /* Assemble the constructor and destructor tables.
  89.      Link the tables in with the rest of the program. */
  90.  
  91.   sprintf (cmd, "as -o %s %s && ld -o %s %s %s && rm %s %s %s",
  92.        hookofile, hooksfile, 
  93.        outfile, codefile, hookofile,
  94.        codefile, hooksfile, hookofile);
  95.   exit (system (cmd));
  96. }
  97.  
  98. /* Scan the name list of the loaded program for the symbols g++ uses
  99.    for static constructors and destructors.  Write their addresses
  100.    into tables which __main and exit will call.
  101.  
  102.    The constructor table __CTOR_LIST__ is an integer count followed by
  103.    that many pointers to constructor functions.  The destructor table
  104.    __DTOR_LIST__ is the same thing, followed by a zero word. */
  105.  
  106. write_hooks (FILE *inf, FILE *outf)
  107. {
  108.   char *p, buf[1024];
  109.   struct id *newid;
  110.  
  111.   struct id *constructors = 0;
  112.   struct id *destructors = 0;
  113.  
  114.   while (! feof (inf)) {
  115.  
  116.     /* Read a line of nm output and strip the trailing newline. */
  117.  
  118.     fgets (buf, sizeof buf, inf);
  119.     p = buf + strlen (buf) - 1;
  120.     if (*p == '\n')
  121.       *p = '\0';
  122.  
  123.     /* If it contains a constructor or destructor name, add the name
  124.        to the appropriate list. */
  125.  
  126.     for (p = buf; *p; p++)
  127.       {
  128.     while (*p && *p != '_')
  129.       p++;
  130.     if (! strncmp (p, "_GLOBAL_$I$", 11))
  131.       {
  132.         newid = alloca (sizeof *newid);
  133.         newid->name = alloca (strlen (p) + 1);
  134.         strcpy (newid->name, p);
  135.         newid->next = constructors;
  136.         constructors = newid;
  137.         break;
  138.       }
  139.     else if (! strncmp (p, "_GLOBAL_$D$", 11))
  140.       {
  141.         newid = alloca (sizeof *newid);
  142.         newid->name = alloca (strlen (p) + 1);
  143.         strcpy (newid->name, p);
  144.         newid->next = destructors;
  145.         destructors = newid;
  146.         break;
  147.       }
  148.       }
  149.   }
  150.  
  151.   /* Write the tables. */
  152.  
  153.   fprintf (outf, "%s\n", TEXT_SECTION_ASM_OP);
  154.   ASM_GLOBALIZE_LABEL (outf, "__CTOR_LIST__");
  155.   ASM_OUTPUT_LABEL (outf, "__CTOR_LIST__");
  156.   ASM_OUTPUT_INT (outf, count_list (constructors));
  157.   write_list (outf, constructors);
  158.   
  159.   fprintf (outf, "%s\n", DATA_SECTION_ASM_OP);
  160.   ASM_GLOBALIZE_LABEL (outf, "__DTOR_LIST__");
  161.   ASM_OUTPUT_LABEL (outf, "__DTOR_LIST__");
  162.   ASM_OUTPUT_INT (outf, count_list (destructors));
  163.   write_list (outf, destructors);
  164.   ASM_OUTPUT_INT (outf, 0);
  165. }
  166.  
  167. /* Length of list LIST. */
  168.  
  169. count_list (struct id *list)
  170. {
  171.   int count = 0;
  172.   while (list)
  173.     {
  174.       count++;
  175.       list = list->next;
  176.     }
  177.   return count;
  178. }
  179.  
  180. /* Write the names on list LIST, in reverse order. */
  181.  
  182. write_list (FILE *outf, struct id *list)
  183. {
  184.   if (! list)
  185.     return;
  186.   write_list (outf, list->next);
  187.   ASM_OUTPUT_LABELREF (outf, list->name);
  188. }
  189.  
  190. /* Die when sys call fails. */
  191.  
  192. fatal_perror (string, arg)
  193. {
  194.   char buf[80];
  195.   sprintf (buf, string, arg);
  196.   perror (buf);
  197.   exit (1);
  198. }
  199.  
  200. /* Just die. */
  201.  
  202. fatal (string)
  203. {
  204.   fprintf (stderr, string);
  205.   exit (1);
  206. }
  207.